package top.hesisi.springboot3.exception;

import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataAccessException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.resource.NoResourceFoundException;
import top.hesisi.springboot3.base.R;

import java.sql.SQLException;
import java.util.List;

/**
* 全局统一异常处理器
*
* @author hesisi
 */

@Slf4j
//控制器拦截器，所有控制器的方法都会被本类拦截
@ControllerAdvice
public class AppExceptionHandler {

    //@ExceptionHandler是异常处理器，当控制器抛出对应类型的异常时会触发本方法
    @ExceptionHandler(Exception.class)
    //@ResponseBody表示应答结果以json格式返回
    @ResponseBody
    public R<String> handleAppException(Exception ex) {
        log.error("全局异常处理器捕获到异常", ex);
        return R.fail("程序发生异常，请联系管理员", null);
    }

    @ExceptionHandler(DataAccessException.class)
    @ResponseBody
    public R<String> handleException(DataAccessException ex) {
        log.error("全局异常处理器捕获到异常", ex);
        return R.fail("程序发生异常，请联系管理员", null);
    }

    @ExceptionHandler(SQLException.class)
    @ResponseBody
    public R<String> handleException(SQLException ex) {
        log.error("数据库语句发生异常", ex);
        return R.fail("数据库语句异常，请联系管理员", null);
    }

    @ExceptionHandler(NoResourceFoundException.class)
    @ResponseBody
    public R<String> handleException(NoResourceFoundException ex) {
        log.error("请求地址错误", ex);
        return R.fail("请求地址错误，请联系管理员", null);
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseBody
    public R<String> handleException(HttpMessageNotReadableException ex) {
        log.error("提交数据格式不正确", ex);
        return R.fail("提交数据格式不正确", null);
    }

    @ExceptionHandler(AppException.class)
    @ResponseBody
    public R<String> handleException(AppException ex) {
        R<String> r = R.fail(ex.getMessage(), null);
        r.setCode(ex.getCode());
        return r;
    }

    //jion提交参数校验失败的错误处理
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public R<String> handleException(MethodArgumentNotValidException ex) {
        return R.fail(getValidateMessage(ex.getBindingResult().getAllErrors()), null);
    }

    //表单提交参数校验失败的错误处理
    @ExceptionHandler(BindException.class)
    @ResponseBody
    public R<String> handleException(BindException ex) {
        return R.fail(getValidateMessage(ex.getBindingResult().getAllErrors()), null);
    }
    private String getValidateMessage(List<ObjectError> errors) {
        StringBuilder sb = new StringBuilder();
        for (ObjectError error : errors) {
            sb.append(error.getDefaultMessage()).append(",");
        }
        if (!sb.isEmpty()) {
            sb.deleteCharAt(sb.length() - 1);
        }
        return sb.toString();
    }


}
